﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleRest.Core.Routing.Handlers;
using SimpleRest.Core.Exceptions;

namespace SimpleRest.Core
{
    /// <summary>
    /// Delegate used to provide extensibility for Dependency Injection for service type creation.
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public delegate object CreateInstanceHandler(Type type, IHttpRequestMessage request);
    /// <summary>
    /// Delegate used to provide extensibility for controlled error handling.
    /// </summary>
    /// <param name="e"></param>
    public delegate void ErrorHandler(ErrorHandlerEventArgs e);

    /// <summary>
    /// Configuration class that is used when registering service and operation routes.  This configuration drives behavior of
    /// REST pipeline requests and allows the developer to control and gain visibility into pieces of the pipeline.
    /// </summary>
    public class Configuration
    {
        /// <summary>
        /// Invoked when an error during the pipeline occurs.
        /// </summary>
        public ErrorHandler ErrorHandler { get; set; }
        /// <summary>
        /// Invoked when service creation is being requested.  Defaults to Activator.CreateInstance(type).
        /// </summary>
        public CreateInstanceHandler CreateServiceInstance { get; set; }
        /// <summary>
        /// When added, a message handler provides visibility into the very beginning of the pipeline and the very end
        /// of the pipeline allowing the creator to manipulate input and output of the request/response.
        /// </summary>
        public List<IHttpMessageHandler> MessageHandlers { get; set; }
        /// <summary>
        /// Very important.  Media type formatters are the mechanisms that provide serialization/deserialization functionality.  When an incoming request
        /// is detected a media type formatter must be determined for the request and the response.  In the event that a media type formatter could not be
        /// determined it is said that the REST request cannot be completed and the pipeline will throw an exception.
        /// </summary>
        public IEnumerable<IMediaTypeFormatter> MediaTypeFormatters { get; set; }

        public Configuration()
        {
            this.CreateServiceInstance = (type, request) =>
            {
                return Activator.CreateInstance(type);
            };

            // fix this so it makes sense
            this.ErrorHandler = (e) =>
            {
                if (e.Exception != null)
                {
                    e.ResponseMessage.ResponseHeaders.Add(new Header("x-error-message", e.Exception.Message));

                    if (e.Exception is NotImplementedException || e.Exception is InvalidOperationException || e.Exception is NotSupportedException)
                    {
                        e.ResponseMessage.StatusCode = System.Net.HttpStatusCode.NotImplemented;
                    }
                    else if (e.Exception is ArgumentNullException || e.Exception is ArgumentException)
                        e.ResponseMessage.StatusCode = System.Net.HttpStatusCode.BadRequest;
                    else if (e.Exception is WebExceptionBase)
                    {
                        WebExceptionBase wEx = e.Exception as Exceptions.WebExceptionBase;
                        e.ResponseMessage.StatusCode = wEx.StatusCode;
                        if (!string.IsNullOrEmpty(wEx.ErrorCode))
                            e.ResponseMessage.ResponseHeaders.Add(new Header("x-error-code", wEx.ErrorCode));
                    }
                    else
                        e.ResponseMessage.StatusCode = System.Net.HttpStatusCode.BadRequest;
                }
                else
                    e.ResponseMessage.StatusCode = System.Net.HttpStatusCode.BadRequest;
            };

            this.MessageHandlers = new List<IHttpMessageHandler>();
        }
    }
}
